package com.changan.alm2.version.common.config;

import cn.hutool.core.util.StrUtil;
import com.changan.alm2.version.common.bean.ResultCode;
import com.changan.alm2.version.common.bean.resp.CommonResult;
import com.changan.alm2.version.common.exception.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.ui.Model;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;

/**
 * 统一异常处理器
 *
 * @Author yaodong
 * @Date 2022/10/14 9:41 AM
 * @Version 1.0
 */
@ControllerAdvice
public class WebExceptionAdvice {
    Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 在其执行之前初始化数据绑定器
   <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.68</version>
            <scope>compile</scope>
        </dependency>     * @param binder
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {
    }

    /**
     * 把值绑定到model,使全局model可以获取到该值
     *
     * @param model
     */
    @ModelAttribute
    public void addAttributes(Model model) {
    }

    /**
     * 全局异常捕捉处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public CommonResult errorHandler(Exception e, HttpServletRequest request) {
        StringBuffer uri = request.getRequestURL();
        CommonResult error;
        if (StrUtil.isEmpty(e.getMessage())) {
            error = CommonResult.error(ResultCode.INTERNAL_SERVER_ERROR);
        } else {
            error = CommonResult.error(e.getMessage());
        }
        logger.error("uri={},msgCode={},msg={}.", uri, error.getStatus(), error.getMessage(), e);
        return error;
    }

    /**
     * 全局异常捕捉处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(value = BusinessException.class)
    @ResponseBody
    public CommonResult errorHandler(BusinessException exception, HttpServletRequest request) {
        StringBuffer uri = request.getRequestURL();
        logger.error("uri={},msgCode={},msg={}.", uri, exception.getResult(), exception.getResultDesc(), exception);
        return new CommonResult(exception.getResult(), exception.getResultDesc());
    }

    /**
     * 处理全局参数校验错误问题
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    @ResponseBody
    public CommonResult errorHandler(ConstraintViolationException e, HttpServletRequest request) {
        StringBuffer uri = request.getRequestURL();
        CommonResult commonResult = new CommonResult(ResultCode.ERROR_PARAMETER.getCode(), e.getLocalizedMessage().split(":")[1]);
        logger.error("uri={},错误信息:{}", uri, commonResult.getMessage(), e);
        return commonResult;
    }

    /**
     * 处理全局参数校验错误问题
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    @ResponseBody
    public CommonResult errorHandler(MissingServletRequestParameterException e, HttpServletRequest request) {
        StringBuffer uri = request.getRequestURL();
        CommonResult commonResult = new CommonResult(ResultCode.ERROR_PARAMETER.getCode(), e.getParameterName() + "不能为空");
        logger.error("uri={},错误信息:{}", uri, commonResult.getMessage(), e);
        return commonResult;
    }


    /**
     * 处理全局参数校验错误问题
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
    @ResponseBody
    public CommonResult errorHandler(MethodArgumentTypeMismatchException e, HttpServletRequest request) {
        StringBuffer uri = request.getRequestURL();
        Class<?> requiredType = e.getRequiredType();
        logger.error("uri={},错误信息", uri, e);

        if (requiredType.equals(Integer.class) || requiredType.equals(Long.class)) {
            return new CommonResult(ResultCode.ERROR_PARAMETER.getCode(), e.getName() + "必须是数字");

        } else {
            return new CommonResult(ResultCode.ERROR_PARAMETER.getCode(), e.getName() + "类型错误");

        }
    }

    /**
     * 实体参数验证错误处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseBody
    public CommonResult errorHandler(MethodArgumentNotValidException e, HttpServletRequest request) {

        StringBuffer uri = request.getRequestURL();
        FieldError fieldError = e.getBindingResult().getFieldError();
        CommonResult commonResult = new CommonResult(ResultCode.ERROR_PARAMETER.getCode(), fieldError.getDefaultMessage());
        logger.error("uri={},错误信息:{}", uri, commonResult.getMessage(), e);
        return commonResult;
    }


    /**
     * 实体参数验证错误处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = BindException.class)
    @ResponseBody
    public CommonResult errorHandler(BindException e, HttpServletRequest request) {

        StringBuffer uri = request.getRequestURL();
        FieldError fieldError = e.getBindingResult().getFieldError();
        CommonResult commonResult = new CommonResult(ResultCode.ERROR_PARAMETER.getCode(), /*fieldError.getField() +*/ fieldError.getDefaultMessage());
        logger.error("uri={},错误信息:{}", uri, commonResult.getMessage(), e);
        return commonResult;
    }

    /**
     * 实体参数验证错误处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    @ResponseBody
    public CommonResult errorHandler(HttpMessageNotReadableException e, HttpServletRequest request) {

        StringBuffer uri = request.getRequestURL();
        CommonResult commonResult = new CommonResult(ResultCode.ERROR_PARAMETER);
        logger.error("uri={},错误信息:{}", uri, commonResult.getMessage(), e);
        return commonResult;
    }


    /**
     * IllegalArgumentException异常信息单独处理不能正常解析的问题?????
     *
     * @param e
     * @return
     */
    //@ExceptionHandler(IllegalArgumentException.class)
    public CommonResult handleHttpMediaTypeNotSupportedException(Exception e) {
        if (logger.isDebugEnabled()) {
            logger.error(e.getMessage(), e);
        }
        return CommonResult.error(e.getMessage());
    }


}
